﻿#include <QDateTime>
#include <Configuration.h>
#include <QTextCodec>
#include <Constants.h>
#include <Utils.h>
#include "EditorSettingsWidget.h"
#include "ui_EditorSettingsWidget.h"
#include "NewColorSchemeDialog.h"

namespace Domy {

EditorSettingsWidget::EditorSettingsWidget(QWidget *parent)
    : AbstractSettingsWidget(parent),
    m_ui(new Ui::EditorSettingsWidget)
{
    m_ui->setupUi(this);

    m_ui->comboBox_scheme->addItems(domy_config->getAllSchemeNames());

    m_ui->comboBox_encoding->addItems(Utils::getAllCodecNames());

    initSettings();

    connect(m_ui->fontComboBox_family, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->comboBox_size, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->comboBox_tab_policy, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->comboBox_tab_size, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->comboBox_encoding, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->frame_bg_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->frame_bg_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnBackgroundColorChanged(const QColor &)));
    connect(m_ui->frame_ln_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->frame_ln_bg_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->comboBox_scheme, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOnSettingsChanged()));

    connect(m_ui->comboBox_scheme, SIGNAL(currentTextChanged(const QString &)), this, SLOT(slotOnSchemeChanged(const QString &)));
    connect(m_ui->listWidget_text_item, SIGNAL(itemSelectionChanged()), this, SLOT(slotOnItemSelectionChanged()));
    connect(m_ui->frame_text_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->checkBox_text_bold, SIGNAL(clicked(bool)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->checkBox_text_italic, SIGNAL(clicked(bool)), this, SLOT(slotOnSettingsChanged()));
    connect(m_ui->checkBox_text_underline, SIGNAL(clicked(bool)), this, SLOT(slotOnSettingsChanged()));

    connect(m_ui->frame_text_color, SIGNAL(signalColorChanged(const QColor &)), this, SLOT(slotOnSchemeParamChanged()));
    connect(m_ui->checkBox_text_bold, SIGNAL(clicked(bool)), this, SLOT(slotOnSchemeParamChanged()));
    connect(m_ui->checkBox_text_italic, SIGNAL(clicked(bool)), this, SLOT(slotOnSchemeParamChanged()));
    connect(m_ui->checkBox_text_underline, SIGNAL(clicked(bool)), this, SLOT(slotOnSchemeParamChanged()));

    connect(m_ui->pushButton_copy, SIGNAL(clicked()), this, SLOT(slotOnCopyBtnClicked()));
    connect(m_ui->pushButton_delete, SIGNAL(clicked()), this, SLOT(slotOnDelBtnClicked()));

    slotOnSchemeChanged(domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_SchemeName).toString());

}

EditorSettingsWidget::~EditorSettingsWidget()
{
    delete m_ui;
}

void EditorSettingsWidget::apply()
{
    if (!this->m_is_changed) {
        return;
    }

    const QString scheme_name = m_ui->comboBox_scheme->currentText();

    // 更新设置项的值
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_Family, m_ui->fontComboBox_family->currentFont().family());
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_FontSize, m_ui->comboBox_size->currentText().toInt());
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_SchemeName, scheme_name);
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_TabPolicy, m_ui->comboBox_tab_policy->currentIndex());
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_TabSize, m_ui->comboBox_tab_size->currentText().toInt());
    domy_config->setSettingsValue(SettingsGroup_Editor, SettingsKey_Encoding, m_ui->comboBox_encoding->currentText());

    // 更新配色方案项的值
    domy_config->setColorSchemeValue(scheme_name, SettingsKey_BGColor, m_ui->frame_bg_color->getColor().name(QColor::HexRgb));
    domy_config->setColorSchemeValue(scheme_name, SettingsKey_LNTextColor, m_ui->frame_ln_color->getColor().name(QColor::HexRgb));
    domy_config->setColorSchemeValue(scheme_name, SettingsKey_LNBGColor, m_ui->frame_ln_bg_color->getColor().name(QColor::HexRgb));

    for (int i = 0; i < m_ui->listWidget_text_item->count(); ++i) {
        QListWidgetItem *item = m_ui->listWidget_text_item->item(i);
        if (item) {
            if (item->text() == tr("Current Line")) {
                domy_config->setColorSchemeValue(scheme_name, SettingsKey_CurrentLine, item->backgroundColor().name(QColor::HexRgb));
            }
            else if (item->text() == tr("Search")) {
                domy_config->setColorSchemeValue(scheme_name, SettingsKey_Search, item->backgroundColor().name(QColor::HexRgb));
            }
            else {
                QString key;
                if (item->text() == tr("Text")) {
                    key = SettingsKey_Text;
                }
                else if (item->text() == tr("Tag")) {
                    key = SettingsKey_Tag;
                }
                else if (item->text() == tr("Attribute")) {
                    key = SettingsKey_Attr;
                }
                else if (item->text() == tr("Attribute Text")) {
                    key = SettingsKey_AttrText;
                }
                else if (item->text() == tr("Comment")) {
                    key = SettingsKey_Comment;
                }
                else {
                    continue;
                }

                QFont font = item->font();
                QStringList params;
                params << item->foreground().color().name(QColor::HexRgb);
                params << (font.bold() ? "true" : "false");
                params << (font.italic() ? "true" : "false");
                params << (font.underline() ? "true" : "false");

                domy_config->setColorSchemeValue(scheme_name, key, params);
            }
        }
    }

    this->m_is_changed = false;
}

void EditorSettingsWidget::restoreDefault()
{
    // 恢复默认参数
    m_ui->fontComboBox_family->setCurrentFont(QFont(DefaultSettings_FontFamily));

    m_ui->comboBox_tab_policy->setCurrentIndex(DefaultSettings_TabPolicy);

    m_ui->comboBox_tab_size->setCurrentText(QString::number(DefaultSettings_TabSize));

    m_ui->comboBox_size->setCurrentText(QString::number(DefaultSettings_FontSize));

    m_ui->comboBox_scheme->setCurrentText(DefaultSettings_SchemeName);

    m_ui->comboBox_encoding->setCurrentText(DefaultSettings_Encoding);
}

void EditorSettingsWidget::slotOnSchemeChanged(const QString &name)
{
    bool param_enable = (name != SchemeName_Light && name != SchemeName_Dark && name != SchemeName_Origin);

    m_ui->pushButton_delete->setEnabled(param_enable);
    m_ui->groupBox_param->setEnabled(param_enable);
    m_ui->groupBox_bg->setEnabled(param_enable);
    m_ui->groupBox_ln->setEnabled(param_enable);

    m_ui->listWidget_text_item->clear();
    m_ui->frame_text_color->setColor(Qt::black);
    m_ui->checkBox_text_bold->setChecked(false);
    m_ui->checkBox_text_italic->setChecked(false);
    m_ui->checkBox_text_underline->setChecked(false);

    // 添加配色方案设置项列表
    auto add_list_item = [&](const QString &name, const QString &key, const QString &text) {

        QStringList list = domy_config->getColorSchemeValue(name, key).toStringList();

        QListWidgetItem *item = new QListWidgetItem(text, m_ui->listWidget_text_item);
        QFont font(domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Family).toString());
        font.setPixelSize(18);
        font.setBold(list.at(SchemeParam_Bold) == "true" ? true : false);
        font.setItalic(list.at(SchemeParam_Italic) == "true" ? true : false);
        font.setUnderline(list.at(SchemeParam_Underline) == "true" ? true : false);

        item->setFont(font);
        item->setForeground(QBrush(QColor(list.at(SchemeParam_Color))));

        m_ui->listWidget_text_item->addItem(item);

    };
    // 添加配色方案设置项列表
    add_list_item(name, SettingsKey_Text, tr("Text"));
    add_list_item(name, SettingsKey_Tag, tr("Tag"));
    add_list_item(name, SettingsKey_Attr, tr("Attribute"));
    add_list_item(name, SettingsKey_AttrText, tr("Attribute Text"));
    add_list_item(name, SettingsKey_Comment, tr("Comment"));

    {
        QColor color(domy_config->getColorSchemeValue(name, SettingsKey_CurrentLine).toString());
        QListWidgetItem *item = new QListWidgetItem(tr("Current Line"), m_ui->listWidget_text_item);
        QFont font(domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Family).toString());
        font.setPixelSize(18);
        item->setFont(font);
        item->setBackground(QBrush(color));
        item->setForeground(QBrush(Utils::getReverseForegroundColor(color)));

        m_ui->listWidget_text_item->addItem(item);
    }

    {
        QColor color(domy_config->getColorSchemeValue(name, SettingsKey_Search).toString());
        QListWidgetItem *item = new QListWidgetItem(tr("Search"), m_ui->listWidget_text_item);
        QFont font(domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Family).toString());
        font.setPixelSize(18);
        item->setFont(font);
        item->setBackground(QBrush(color));
        item->setForeground(QBrush(Utils::getReverseForegroundColor(color)));
    }

    m_ui->frame_bg_color->setColor(domy_config->getColorSchemeValue(name, SettingsKey_BGColor).toString());
    m_ui->frame_ln_color->setColor(domy_config->getColorSchemeValue(name, SettingsKey_LNTextColor).toString());
    m_ui->frame_ln_bg_color->setColor(domy_config->getColorSchemeValue(name, SettingsKey_LNBGColor).toString());

    m_ui->listWidget_text_item->setCurrentItem(m_ui->listWidget_text_item->item(0));
}

void EditorSettingsWidget::slotOnItemSelectionChanged()
{
    QListWidgetItem *item = m_ui->listWidget_text_item->currentItem();
    if (!item) {
        return;
    }

    QFont font = item->font();
    m_ui->checkBox_text_bold->setChecked(font.bold());
    m_ui->checkBox_text_italic->setChecked(font.italic());
    m_ui->checkBox_text_underline->setChecked(font.underline());

    bool font_param_enable = false;
    if (item->text() == tr("Current Line")
            || item->text() == tr("Search")) {
        m_ui->frame_text_color->setColor(item->background().color());
    }
    else {
        m_ui->frame_text_color->setColor(item->foreground().color());
        font_param_enable = true;
    }

    m_ui->checkBox_text_bold->setEnabled(font_param_enable);
    m_ui->checkBox_text_italic->setEnabled(font_param_enable);
    m_ui->checkBox_text_underline->setEnabled(font_param_enable);
}

void EditorSettingsWidget::slotOnCopyBtnClicked()
{
    NewColorSchemeDialog *dialog = new NewColorSchemeDialog(QString("%1_copy_%2")
                                                            .arg(m_ui->comboBox_scheme->currentText())
                                                            .arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss")), this);
    connect(dialog, SIGNAL(signalNewSchemeName(const QString &)), this, SLOT(slotOnNewSchemeName(const QString &)));
    dialog->exec();

    delete dialog;
    dialog = Q_NULLPTR;
}

void EditorSettingsWidget::slotOnDelBtnClicked()
{
    if (domy_config->deleteColorScheme(m_ui->comboBox_scheme->currentText())) {
        int index = m_ui->comboBox_scheme->currentIndex();

        m_ui->comboBox_scheme->setCurrentText(SchemeName_Light);

        m_ui->comboBox_scheme->removeItem(index);

    }
}

void EditorSettingsWidget::slotOnNewSchemeName(const QString &name)
{
    if (domy_config->copyColorScheme(m_ui->comboBox_scheme->currentText(), name)) {
        m_ui->comboBox_scheme->addItem(name);
        m_ui->comboBox_scheme->setCurrentText(name);
    }
}

void EditorSettingsWidget::slotOnSchemeParamChanged()
{
    QListWidgetItem *item = m_ui->listWidget_text_item->currentItem();
    if (!item) {
        return;
    }

    if (item->text() == tr("Current Line")
            || item->text() == tr("Search")) {
        item->setBackgroundColor(m_ui->frame_text_color->getColor());
        item->setForeground(Utils::getReverseForegroundColor(m_ui->frame_text_color->getColor()));
    }
    else {
        QFont font = item->font();
        font.setFamily(domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Family).toString());
        font.setBold(m_ui->checkBox_text_bold->isChecked());
        font.setItalic(m_ui->checkBox_text_italic->isChecked());
        font.setUnderline(m_ui->checkBox_text_underline->isChecked());
        item->setFont(font);

        item->setForeground(m_ui->frame_text_color->getColor());
    }
}

void EditorSettingsWidget::slotOnBackgroundColorChanged(const QColor &color)
{
    m_ui->listWidget_text_item->setStyleSheet(QString("QListWidget#%1 { background-color: rgb(%2, %3, %4); }")
                                              .arg(m_ui->listWidget_text_item->objectName())
                                              .arg(color.red())
                                              .arg(color.green())
                                              .arg(color.blue()));
}

void EditorSettingsWidget::initSettings()
{
    QString family = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Family).toString();
    m_ui->fontComboBox_family->setCurrentFont(QFont(family));

    int size = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_FontSize).toInt();
    m_ui->comboBox_size->setCurrentText(QString::number(size));

    int tab_policy = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_TabPolicy).toInt();
    m_ui->comboBox_tab_policy->setCurrentIndex(tab_policy);

    int tab_size = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_TabSize).toInt();
    m_ui->comboBox_tab_size->setCurrentText(QString::number(tab_size));

    QString scheme = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_SchemeName).toString();
    m_ui->comboBox_scheme->setCurrentText(scheme);

    QString encoding = domy_config->getSettingsValue(SettingsGroup_Editor, SettingsKey_Encoding).toString();
    m_ui->comboBox_encoding->setCurrentText(encoding);
}

} // namespace Domy
